<?php
namespace PsiFramework\Classes\Factory;

import("Classes.Util.Parameters.Action.ActionMapping");
import("Classes.Util.Manager.ApplicationManager");
import("Classes.Util.Manager.ParametersManager");

use \PsiFramework\Classes\Exceptions\SecurityException;
use \PsiFramework\Classes\Util\Application;
use \PsiFramework\Classes\Util\Parameters\Action\ActionParameters;
use \PsiFramework\Classes\Util\Parameters\Action\ActionMapping;
use \PsiFramework\Classes\Util\Manager\ApplicationManager;
use \PsiFramework\Classes\Util\Manager\ParametersManager;
use \PsiFramework\Classes\Util\Security\Manager\SecurityManager;

/**
 * Bibliotheque
 * Gestion de ma bibliothèque
 *
 * @author Rémi San
 * @version beta
 */


/**
 * The ActionFactory is used to get the correct Action instance
 *
 * @package Factories
 */
class ActionFactory
{

    protected static /*ActionFactory*/ $_singleton = null;

    protected /*ActionMapping*/ $_actionMapping ;
    /**
     * The application
     * 
     * @var \PsiFramework\Classes\Util\Application
     */
    protected /*Application*/   $_application ;

    protected function __construct()
    {
        $paramManager = ParametersManager::getInstance();
        $this->_application
            = ApplicationManager::getInstance()->getApplication();
    }

    /**
     * Static function to retrieve a new instance of
     * the action based on its name
     *
     * @param     string     $actionName    the action name
     * @return     IAction    $action        the wanted IAction
     */
    public function getAction(
        /*string*/ $actionName,
        /*boolean*/ $securityCheck=true
    )
    {
        if (isNullOrEmptyString($actionName)) {
            $actionName = $this->_application->getDefaultActionName();
        }

        if ($securityCheck) {
            $securityManager = SecurityManager::getInstance();
            if (!$securityManager->canExecuteAction(
                $actionName,
                $this->_application
            )
            ) {
                throw new SecurityException(
                    "User can't execute the Action '".$actionName."' !"
                );
            }
        }

        $actionParameters = $this->_application->getAction($actionName);
        if ($actionParameters === null) {
            return null;
        }
        
        return self::getAndImportAction($actionParameters);
    }

    public static function getAndImportAction(ActionParameters $actionParameters)
    {
        if (is_null($actionParameters)) {
            return null ;
        }

        $actionName = $actionParameters->getClass();
        if ($actionName === null) {
            return null;
        }
        
        import($actionName);
        $actionName = getClassName($actionName);
        
        if (class_exists($actionName)) {
            return new $actionName($actionParameters);
        } else {
            return null ;
        }
    }

    /**
     * Function to be called instead of the constructor.
     *
     * @return ActionFactory instance
     */
    public static function getInstance()
    {

        if (self::$_singleton==null) {
            self::$_singleton = new ActionFactory();
        }

        return self::$_singleton;
    }
}
